// This makes a simple robot arm, rather like the bendable arm in program bar.java.
// For fun this uses the GLUT library for drawing parts of the arm.


	
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.Frame;
import java.awt.GridLayout;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.media.opengl.*;
import javax.media.opengl.glu.*;

import javax.media.opengl.awt.GLCanvas;
import com.jogamp.opengl.util.*;
import com.jogamp.opengl.util.gl2.*;
import java.awt.*;
import javax.swing.*;

import java.awt.event.*;
import javax.swing.event.*;



public class Figure implements GLEventListener, ActionListener, ChangeListener {
	
	public static void main(String[] args) {
		new Figure();
	}
	
	private int INITIAL_WIDTH=900;
	private int INITIAL_HEIGHT=800;
	
	private GLCanvas canvas;
	private GL2 gl;
	private GLU glu;
	private GLUT glut;
	// viewer position (5, 10, 40)
	private float viewerX = 5f;
	private float viewerY  = 10f;
	private float viewerZ = 40f;
	
	JButton quitButton, bodyButton, leftArmButton, rightArmButton, leftLegButton, rightLegButton;
	private JSlider bodyAngleSlider, headAngle1Slider, headAngle2Slider, upperLeftArmSlider;
	private JSlider lowerLeftArmSlider, upperRightArmSlider, lowerRightArmSlider, upperLeftLegSlider;
	private JSlider lowerLeftLegSlider, upperRightLegSlider, lowerRightLegSlider;
	private JFrame bodyFrame, rightArmFrame, leftArmFrame, rightLegFrame, leftLegFrame;
	private boolean bodyControlsVisible = false;
	private boolean rightArmControlsVisible = false;
	private boolean leftArmControlsVisible = false;
	private boolean rightLegControlsVisible = false;
	private boolean leftLegControlsVisible = false;
	
	private float bodyAngle = 65f;
	private float headAngle1 = 0f;
	private float headAngle2 = 0f;
	private float upperRightArmAngle = -42f;
	private float lowerRightArmAngle = -12f;
	private float upperLeftArmAngle = -33f;
	private float lowerLeftArmAngle = -48f;
	private float upperRightLegAngle = 18f;
	private float lowerRightLegAngle = 74f;
	private float upperLeftLegAngle = -14f;
	private float lowerLeftLegAngle = 11f;

	private float torsoRadius = 2f;
	private float torsoHeight = 6f;
	private float headX = 0f;
	private float headY = 7.5f;
	private float headRadius = 2f;
	private float eyeRadius = 0.2f;
	private float rightEyeX = -0.7f;
	private float leftEyeX = 0.7f;
	private float eyeZ = 1.6f;
	private float eyeY = 0.7f;
	private float armRadius = 0.4f;
	private float upperArmLength = 3f;
	private float lowerArmLength = 3f;
	private float leftArmX = 2f;
	private float leftUpperArmY = 5;
	private float leftLowerArmY = -3f;
	private float rightArmX = -2f;
	private float rightUpperArmY = 5;
	private float rightLowerArmY = -3f;
	private float legRadius = 0.4f;
	private float upperLegLength = 4f;
	private float lowerLegLength = 4f;
	private float leftLegX = 2f;
	private float leftUpperLegY = 0;
	private float leftLowerLegY = -4f;
	private float rightLegX = -2f;
	private float rightUpperLegY = 0;
	private float rightLowerLegY = -4f;

	private GLUquadric quad1, quad2;
	
	public  Figure() {
			GLProfile glp=GLProfile.getDefault();
			GLCapabilities caps = new GLCapabilities(glp);
			canvas = new GLCanvas(caps);
			JFrame frame = new JFrame("Figure");
			frame.setSize(INITIAL_WIDTH, INITIAL_HEIGHT);
			frame.setLayout(new BorderLayout());
			JPanel north = new JPanel( new FlowLayout(FlowLayout.LEADING));
			
			quitButton = new JButton( "Quit");
			quitButton.addActionListener(this);
			north.add(quitButton);
			
			bodyButton = new JButton( "Body Angles");
			bodyButton.addActionListener(this);
			north.add(bodyButton);
			rightArmButton = new JButton( "Right Arm Angles");
			rightArmButton.addActionListener(this);
			north.add(rightArmButton);			
			leftArmButton = new JButton( "Left Arm Angles");
			leftArmButton.addActionListener(this);
			north.add(leftArmButton);			
			rightLegButton = new JButton( "Right Leg Angles");
			rightLegButton.addActionListener(this);
			north.add(rightLegButton);			
			leftLegButton = new JButton( "Left Leg Angles");
			leftLegButton.addActionListener(this);
			north.add(leftLegButton); 
			
			bodyFrame = new JFrame("Body Angles");
			bodyFrame.setSize(600, 300);
			bodyFrame.setLayout(new GridLayout(3, 1));
			bodyFrame.setVisible(false);	
			bodyFrame.setAlwaysOnTop(true);
			bodyFrame.setLocation(800, 50);

			JPanel firstRow = new JPanel(new BorderLayout());
			bodyAngleSlider = new JSlider(-180, 180);
			bodyAngleSlider.setValue((int)(bodyAngle));
			bodyAngleSlider.setMajorTickSpacing(45);
			bodyAngleSlider.setPaintTicks(true);
			bodyAngleSlider.setPaintLabels(true);
			bodyAngleSlider.addChangeListener(this);
			JLabel bodyAngleSliderName = new JLabel("   Body Angle");
			firstRow.add(bodyAngleSliderName, BorderLayout.WEST);
			firstRow.add(bodyAngleSlider, BorderLayout.CENTER);
			bodyFrame.add(firstRow);

			JPanel secondRow = new JPanel(new BorderLayout());
			headAngle1Slider = new JSlider(-10, 15);
			headAngle1Slider.setValue((int)(headAngle1));
			headAngle1Slider.setMajorTickSpacing(5);
			headAngle1Slider.setPaintTicks(true);
			headAngle1Slider.setPaintLabels(true);
			headAngle1Slider.addChangeListener(this);
			JLabel headAngle1SliderName = new JLabel("   Head Angle 1");
			secondRow.add(headAngle1SliderName, BorderLayout.WEST);
			secondRow.add(headAngle1Slider, BorderLayout.CENTER);
			bodyFrame.add(secondRow);
			
			JPanel thirdRow = new JPanel(new BorderLayout());
			headAngle2Slider = new JSlider(-90, 90);
			headAngle2Slider.setValue((int)(headAngle2));
			headAngle2Slider.setMajorTickSpacing(45);
			headAngle2Slider.setPaintTicks(true);
			headAngle2Slider.setPaintLabels(true);
			headAngle2Slider.addChangeListener(this);
			JLabel headAngle2SliderName = new JLabel("   Head Angle 2");
			thirdRow.add(headAngle2SliderName, BorderLayout.WEST);
			thirdRow.add(headAngle2Slider, BorderLayout.CENTER);
			bodyFrame.add(thirdRow);
			
			
			rightArmFrame = new JFrame("Right Arm Angles");
			rightArmFrame.setSize(600, 300);
			rightArmFrame.setLayout(new GridLayout(2, 1));
			rightArmFrame.setVisible(false);	
			rightArmFrame.setAlwaysOnTop(true);
			rightArmFrame.setLocation(800, 50);
			
			JPanel fourthRow = new JPanel(new BorderLayout());
			upperRightArmSlider = new JSlider(-180, 90);
			upperRightArmSlider.setValue((int)(upperRightArmAngle));
			upperRightArmSlider.setMajorTickSpacing(45);
			upperRightArmSlider.setPaintTicks(true);
			upperRightArmSlider.setPaintLabels(true);
			upperRightArmSlider.addChangeListener(this);
			JLabel upperRightArmSliderName = new JLabel("   Upper Right Arm Angle");
			fourthRow.add(upperRightArmSliderName, BorderLayout.WEST);
			fourthRow.add(upperRightArmSlider, BorderLayout.CENTER);
			rightArmFrame.add(fourthRow);

			JPanel fifthRow = new JPanel(new BorderLayout());
			lowerRightArmSlider = new JSlider(-90, 00);
			lowerRightArmSlider.setValue((int)(lowerRightArmAngle));
			lowerRightArmSlider.setMajorTickSpacing(30);
			lowerRightArmSlider.setPaintTicks(true);
			lowerRightArmSlider.setPaintLabels(true);
			lowerRightArmSlider.addChangeListener(this);
			JLabel lowerRightArmSliderName = new JLabel("   Lower Right Arm Angle");
			fifthRow.add(lowerRightArmSliderName, BorderLayout.WEST);
			fifthRow.add(lowerRightArmSlider, BorderLayout.CENTER);
			rightArmFrame.add(fifthRow);

			leftArmFrame = new JFrame("Left Arm Angles");
			leftArmFrame.setSize(600, 300);
			leftArmFrame.setLayout(new GridLayout(2, 1));
			leftArmFrame.setVisible(false);	
			leftArmFrame.setAlwaysOnTop(true);
			leftArmFrame.setLocation(800, 50);
			
			JPanel sixthRow = new JPanel(new BorderLayout());
			upperLeftArmSlider = new JSlider(-180, 90);
			upperLeftArmSlider.setValue((int)(upperLeftArmAngle));
			upperLeftArmSlider.setMajorTickSpacing(45);
			upperLeftArmSlider.setPaintTicks(true);
			upperLeftArmSlider.setPaintLabels(true);
			upperLeftArmSlider.addChangeListener(this);
			JLabel upperLeftArmSliderName = new JLabel("   Upper Left Arm Angle");
			sixthRow.add(upperLeftArmSliderName, BorderLayout.WEST);
			sixthRow.add(upperLeftArmSlider, BorderLayout.CENTER);
			leftArmFrame.add(sixthRow);

			JPanel seventhRow = new JPanel(new BorderLayout());
			lowerLeftArmSlider = new JSlider(-90, 00);
			lowerLeftArmSlider.setValue((int)(lowerLeftArmAngle));
			lowerLeftArmSlider.setMajorTickSpacing(30);
			lowerLeftArmSlider.setPaintTicks(true);
			lowerLeftArmSlider.setPaintLabels(true);
			lowerLeftArmSlider.addChangeListener(this);
			JLabel lowerLeftArmSliderName = new JLabel("   Lower Left Arm Angle");
			seventhRow.add(lowerLeftArmSliderName, BorderLayout.WEST);
			seventhRow.add(lowerLeftArmSlider, BorderLayout.CENTER);
			leftArmFrame.add(seventhRow);

			rightLegFrame = new JFrame("Right Leg Angles");
			rightLegFrame.setSize(600, 300);
			rightLegFrame.setLayout(new GridLayout(2, 1));
			rightLegFrame.setVisible(false);	
			rightLegFrame.setAlwaysOnTop(true);
			rightLegFrame.setLocation(800, 50);
			
			JPanel eighthRow = new JPanel(new BorderLayout());
			upperRightLegSlider = new JSlider(-90, 90);
			upperRightLegSlider.setValue((int)(upperRightLegAngle));
			upperRightLegSlider.setMajorTickSpacing(45);
			upperRightLegSlider.setPaintTicks(true);
			upperRightLegSlider.setPaintLabels(true);
			upperRightLegSlider.addChangeListener(this);
			JLabel upperRightLegSliderName = new JLabel("   Upper Right Leg Angle");
			eighthRow.add(upperRightLegSliderName, BorderLayout.WEST);
			eighthRow.add(upperRightLegSlider, BorderLayout.CENTER);
			rightLegFrame.add(eighthRow);

			JPanel ninethRow = new JPanel(new BorderLayout());
			lowerRightLegSlider = new JSlider(0, 90);
			lowerRightLegSlider.setValue((int)(lowerRightLegAngle));
			lowerRightLegSlider.setMajorTickSpacing(30);
			lowerRightLegSlider.setPaintTicks(true);
			lowerRightLegSlider.setPaintLabels(true);
			lowerRightLegSlider.addChangeListener(this);
			JLabel lowerRightLegSliderName = new JLabel("   Lower Right Leg Angle");
			ninethRow.add(lowerRightLegSliderName, BorderLayout.WEST);
			ninethRow.add(lowerRightLegSlider, BorderLayout.CENTER);
			rightLegFrame.add(ninethRow);

			leftLegFrame = new JFrame("Left Leg Angles");
			leftLegFrame.setSize(600, 300);
			leftLegFrame.setLayout(new GridLayout(2, 1));
			leftLegFrame.setVisible(false);	
			leftLegFrame.setAlwaysOnTop(true);
			leftLegFrame.setLocation(800, 50); 
			
			JPanel tenthRow = new JPanel(new BorderLayout());
			upperLeftLegSlider = new JSlider(-90, 90);
			upperLeftLegSlider.setValue((int)(upperLeftLegAngle));
			upperLeftLegSlider.setMajorTickSpacing(45);
			upperLeftLegSlider.setPaintTicks(true);
			upperLeftLegSlider.setPaintLabels(true);
			upperLeftLegSlider.addChangeListener(this);
			JLabel upperLeftLegSliderName = new JLabel("   Upper Left Leg Angle");
			tenthRow.add(upperLeftLegSliderName, BorderLayout.WEST);
			tenthRow.add(upperLeftLegSlider, BorderLayout.CENTER);
			leftLegFrame.add(tenthRow);

			JPanel eleventhRow = new JPanel(new BorderLayout());
			lowerLeftLegSlider = new JSlider(0, 90);
			lowerLeftLegSlider.setValue((int)(lowerLeftLegAngle));
			lowerLeftLegSlider.setMajorTickSpacing(30);
			lowerLeftLegSlider.setPaintTicks(true);
			lowerLeftLegSlider.setPaintLabels(true);
			lowerLeftLegSlider.addChangeListener(this);
			JLabel lowerLeftLegSliderName = new JLabel("   Lower Left Leg Angle");
			eleventhRow.add(lowerLeftLegSliderName, BorderLayout.WEST);
			eleventhRow.add(lowerLeftLegSlider, BorderLayout.CENTER);
			leftLegFrame.add(eleventhRow);

			frame.add(north, BorderLayout.NORTH);
			JPanel myCanvas = new JPanel(new GridLayout(1,1));
			
			myCanvas.add(canvas);

			frame.add(myCanvas, BorderLayout.CENTER);
			
			frame.setVisible(true);
			canvas.addGLEventListener(this);

			FPSAnimator animator = new FPSAnimator(canvas, 60);
			animator.start(); 
				

	}
	public void actionPerformed(ActionEvent event) {
			if (event.getSource() == quitButton)
				System.exit(0);
			else if (event.getSource() == bodyButton) {
				bodyControlsVisible = !bodyControlsVisible;
				bodyFrame.setVisible(bodyControlsVisible);
			}
			else if (event.getSource() == rightArmButton) {
				rightArmControlsVisible = !rightArmControlsVisible;
				rightArmFrame.setVisible(rightArmControlsVisible);
			}
			else if (event.getSource() == leftArmButton) {
				leftArmControlsVisible = !leftArmControlsVisible;
				leftArmFrame.setVisible(leftArmControlsVisible);
			}
			else if (event.getSource() == rightLegButton) {
				rightLegControlsVisible = !rightLegControlsVisible;
				rightLegFrame.setVisible(rightLegControlsVisible);
			}
			else if (event.getSource() == leftLegButton) {
				leftLegControlsVisible = !leftLegControlsVisible;
				leftLegFrame.setVisible(leftLegControlsVisible);
			} 
	}
	
	public void stateChanged(ChangeEvent e) {
		if (e.getSource() == bodyAngleSlider) {
			bodyAngle = bodyAngleSlider.getValue();
		}
		else if (e.getSource() == headAngle1Slider) {
			headAngle1 = headAngle1Slider.getValue();
		}
		else if (e.getSource() == headAngle2Slider) {
			headAngle2 = headAngle2Slider.getValue();
		}
		else if (e.getSource() == upperRightArmSlider) {
			upperRightArmAngle = upperRightArmSlider.getValue();
		} 
		else if (e.getSource() == lowerRightArmSlider) {
			lowerRightArmAngle = lowerRightArmSlider.getValue();
		} 
		else if (e.getSource() == upperLeftArmSlider) {
			upperLeftArmAngle = upperLeftArmSlider.getValue();
		} 
		else if (e.getSource() == lowerLeftArmSlider) {
			lowerLeftArmAngle = lowerLeftArmSlider.getValue();
		} 
		else if (e.getSource() == upperRightLegSlider) {
			upperRightLegAngle = upperRightLegSlider.getValue();
		} 
		else if (e.getSource() == lowerRightLegSlider) {
			lowerRightLegAngle = lowerRightLegSlider.getValue();
		} 
		else if (e.getSource() == upperLeftLegSlider) {
			upperLeftLegAngle = upperLeftLegSlider.getValue();
		} 
		else if (e.getSource() == lowerLeftLegSlider) {
			lowerLeftLegAngle = lowerLeftLegSlider.getValue();
		} 

	}


	public void display(GLAutoDrawable drawable) {
		update();
		render(drawable);
	}

	private void update() {			
	}

	
	private void render(GLAutoDrawable drawable) {
		gl.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT);
		gl.glPushMatrix();
		
		// body
		gl.glColor3f(1f, 1f, 0f);
		gl.glRotatef(bodyAngle, 0f, 1f, 0f);
		torso();
		
		//head
		gl.glPushMatrix();
		gl.glRotatef(headAngle1, 1f, 0f, 0f);
		gl.glRotatef(headAngle2, 0f, 1f, 0f);
		gl.glTranslatef(0f, headY, 0f);
		head();
		gl.glPopMatrix();
		
		// right arm
		gl.glColor3f(0f, 0f, 1f);
		gl.glPushMatrix();
		gl.glTranslatef(rightArmX, rightUpperArmY, 0);
		gl.glRotatef(upperRightArmAngle, 1f, 0f, 0f);
		rightUpperArm();
		gl.glTranslatef(0f, rightLowerArmY, 0f);
		gl.glRotatef(lowerRightArmAngle, 1f, 0f, 0f);
		rightLowerArm();
		gl.glPopMatrix();
		
		//left arm
		gl.glColor3f(0.0f, 0f, 1f);
		gl.glPushMatrix();
		gl.glTranslatef(leftArmX, leftUpperArmY, 0);
		gl.glRotatef(upperLeftArmAngle, 1f, 0f, 0f);
		leftUpperArm();
		gl.glTranslatef(0f, leftLowerArmY, 0f);
		gl.glRotatef(lowerLeftArmAngle, 1f, 0f, 0f);
		leftLowerArm();
		gl.glPopMatrix();
		
		// left leg
		gl.glColor3f(0.0f, 1f, 0f);
		gl.glPushMatrix();
		gl.glTranslatef(leftLegX, leftUpperLegY, 0);
		gl.glRotatef(upperLeftLegAngle, 1f, 0f, 0f);
		leftUpperLeg();
		gl.glTranslatef(0f, leftLowerLegY, 0f);
		gl.glRotatef(lowerLeftLegAngle, 1f, 0f, 0f);
		leftLowerLeg();
		gl.glPopMatrix();

		// right leg
		gl.glColor3f(0.0f, 1f, 0f);
		gl.glPushMatrix();
		gl.glTranslatef(rightLegX, rightUpperLegY, 0);
		gl.glRotatef(upperRightLegAngle, 1f, 0f, 0f);
		rightUpperLeg();
		gl.glTranslatef(0f, rightLowerLegY, 0f);
		gl.glRotatef(lowerRightLegAngle, 1f, 0f, 0f);
		rightLowerLeg();
		gl.glPopMatrix();
	
		gl.glPopMatrix();
	}
	
	private void head() {
		gl.glColor3f(1f,1f, 1f);
		gl.glPushMatrix();
		gl.glTranslatef(leftEyeX, eyeY, eyeZ);
		gl.glColor3f(1f, 1f, 1f);
		glu.gluSphere(quad2, eyeRadius, 8, 8);
		gl.glPopMatrix();
		gl.glPushMatrix();
		gl.glTranslatef(rightEyeX, eyeY, eyeZ);
		glu.gluSphere(quad2, eyeRadius, 8, 8);
		gl.glPopMatrix();
		gl.glPushMatrix();
		gl.glTranslatef(0f, 0.2f, -0.4f);
		gl.glColor3f(0.7f, 0.5f, 0f);
		glu.gluSphere(quad1, headRadius, 8, 8);
		gl.glPopMatrix();
		gl.glColor3f(1f,  0.7f,  0f);
		glu.gluSphere(quad1, headRadius,  8,  8);
	}
	
	private void torso() {
		gl.glPushMatrix();
		gl.glRotatef(-90f, 1f, 0f, 0f);
		glu.gluCylinder(quad1, torsoRadius, torsoRadius, torsoHeight, 8, 8);
		gl.glPopMatrix();
	}

	private void rightUpperArm() {
		gl.glPushMatrix();
		gl.glRotatef(90f, 1f, 0f, 0f);
		glu.gluCylinder(quad1, armRadius, armRadius, upperArmLength, 8, 8);
		gl.glPopMatrix();
	}
	
	private void rightLowerArm() {
		gl.glPushMatrix();
		gl.glRotatef(90f, 1f, 0f, 0f);
		glu.gluCylinder(quad1, armRadius, armRadius, lowerArmLength, 8, 8);
		gl.glPopMatrix();
	}
	
	private void leftUpperArm() {
		gl.glPushMatrix();
		gl.glRotatef(90f, 1f, 0f, 0f);
		glu.gluCylinder(quad1, armRadius, armRadius, upperArmLength, 8, 8);
		gl.glPopMatrix();
	}
	
	private void leftLowerArm() {
		gl.glPushMatrix();
		gl.glRotatef(90f, 1f, 0f, 0f);
		glu.gluCylinder(quad1, armRadius, armRadius, lowerArmLength, 8, 8);
		gl.glPopMatrix();
	}

	private void leftUpperLeg() {
		gl.glPushMatrix();
		gl.glRotatef(90f, 1f, 0f, 0f);
		glu.gluCylinder(quad1, legRadius, legRadius, upperLegLength, 8, 8);
		gl.glPopMatrix();
	}
	
	private void leftLowerLeg() {
		gl.glPushMatrix();
		gl.glRotatef(90f, 1f, 0f, 0f);
		glu.gluCylinder(quad1, legRadius, legRadius, lowerLegLength, 8, 8);
		gl.glPopMatrix();
	}

	private void rightUpperLeg() {
		gl.glPushMatrix();
		gl.glRotatef(90f, 1f, 0f, 0f);
		glu.gluCylinder(quad1, legRadius, legRadius, upperLegLength, 8, 8);
		gl.glPopMatrix();
	}
	
	private void rightLowerLeg() {
		gl.glPushMatrix();
		gl.glRotatef(90f, 1f, 0f, 0f);
		glu.gluCylinder(quad1, legRadius, legRadius, lowerLegLength, 8, 8);
		gl.glPopMatrix();
	}

	public void dispose(GLAutoDrawable drawable) {
		// put the cleanup code here
		
	}

	public void init(GLAutoDrawable drawable) {
		gl = drawable.getGL().getGL2();
		glu = new GLU();
		glut = new GLUT();
		quad1 = glu.gluNewQuadric();
		quad2 = glu.gluNewQuadric();
		gl.glEnable(GL2.GL_DEPTH_TEST);
		gl.glMatrixMode(GL2.GL_PROJECTION);
		gl.glLoadIdentity();
		glu.gluPerspective(60f, 1f, 0.5f, 200f); 
		gl.glMatrixMode(GL2.GL_MODELVIEW);
		gl.glLoadIdentity();
		glu.gluLookAt(viewerX, viewerY, viewerZ, 0f, 0f, 0f, 0f, 1f, 0f);  
		gl.glClearColor(1,  1, 1, 1);
		gl.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT);
	}

	public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
		// this is called when the window is resized
		gl.glViewport(0, 0, width, height);
		float aspect = width*1.0f/height;
		gl.glMatrixMode(GL2.GL_PROJECTION);
		gl.glLoadIdentity();
		glu.gluPerspective(60f, aspect, 0.5f, 200f); 
		gl.glMatrixMode(GL2.GL_MODELVIEW);
		
		
	}
	
}
